import { defineStore } from "pinia";
import { getToken, removeToken, setToken } from "../utils/token-utils";
import { ElMessage } from "element-plus";
import { staticRoutes,allAsyncRoutes,anyRoute } from "@/router/routes";
import userApi from "@/api/user";
// import userApi,{type LoginParamsData} from "@/api/user";
import type { LoginParamsData, UserInfoData } from "@/api/user";
import type { RouteRecordRaw } from "vue-router";
import router from '@/router'
import cloneDeep from 'lodash/cloneDeep'

interface UserInfoStoreStataeData {
  token: string;
  userInfo: UserInfoData;
  menuRoutes: RouteRecordRaw[];
}
// 封装初始化userInfo这个数据的函数
function initUserInfo() {
  return {
    routes: [], //用户自己的路由权限数据 由字符串所组成的数组 字符串是和咱们路由对象的name所对应
    buttons: [], //用户自己的按钮权限数据 由字符串所组成的数组
    roles: [],
    name: "",
    avatar: "",
  };
}

// ['Product','Sku','Spu]
// 根据所有的动态路由以及用户自己所拥有的权限数据 过滤去用户自己可以拥有的路由
function filterUserRoutes(allAsyncRoutes:RouteRecordRaw[],userRoutesName:string[]){
  let result = allAsyncRoutes.filter(item=>{
    if(userRoutesName.indexOf(item.name as string) !== -1){ //找到了自己所能拥有的那个路由对象
      // 咱们的二级路由也需要进行过滤 根据用户自己所拥有的权限数据
      if(item.children&&item.children.length){
        // 某个用户过滤出来里面的某几个二级路由
        // 下次再有用户进来过滤 过滤的那个二级路由不是所有的了 二次上次过滤完成之后的
        item.children = filterUserRoutes(item.children,userRoutesName)
      }
      return true
    }
  })
  return result
}
// 把用户过滤出来的异步路由增加到路由器中
function addUserAsyncRoutes(userAsyncRoutesAndAnyRoute:RouteRecordRaw[]){
  // 遍历用户自己的异步路由以及任意路由
  // 把他们都增加到路由器中
  userAsyncRoutesAndAnyRoute.forEach(item=>{
    // 使用路由器实例身上的addRoute方法 来去增加路由对象 参数就是要增加的路由对象
    router.addRoute(item)
  })
}
// 用户退出登录需要清除路由器中的路由 防止下一用户进来还能看到之前用户的路由
function clearRoutes(){
  // 获取所有的路由 返回值是所有路由所组成的数组
  let routes = router.getRoutes()
  // 清除所有路由
  routes.forEach(item=>{
    // 使用路由器实例身上的removeRoute方法 来去删除某个路由
    // 参数：要删除路由对象名name属性
    router.removeRoute(item.name as string)
  })
  // 增加静态路由
  addUserAsyncRoutes(staticRoutes)
}

export const useUserInfoStore = defineStore("userInfo", {
  state: (): UserInfoStoreStataeData => ({
    token: localStorage.getItem("token") || "", //token
    userInfo: initUserInfo(), //用户信息
    menuRoutes: staticRoutes, // 应该放置路由对象数组 这个数据在控制菜单生成  菜单是根据路由生成!!!
    //路由对象中meta数据如果hidden:true  那么不会根据这个路由对象生成菜单
  }),

  // 1.修改userinfoStore中的数据及方法
  // 2.获取用户信息及退出登录需要token  请求拦截器中增加token
  // 3.点击登录触发actions方法login传递的参数不对 需要传递一个对象
  // 4.一直再获取用户信息发送请求 把permiss.ts文件中的数据修改
  // 5.home组件显示的内容不正确 navbar组件显示的内容不正确
  // 6.点击退出登录不能触发reset方法 而应该触发logout方法
  actions: {
    // 登录
    async login(loginParams: LoginParamsData) {
      try {
        const res = await userApi.login(loginParams);
        this.token = res.token;
        localStorage.setItem("token", res.token);
        return "ok";
      } catch (error) {
        return Promise.reject("fail");
      }
    },
    // 获取用户信息
    async getInfo() {
      try {
        const res = await userApi.info();
        this.userInfo = res;
        // 1.根据所有的动态路由以及用户自己所拥有的权限数据 过滤去用户自己可以拥有的路由
        let useAsyncRoutes = filterUserRoutes(cloneDeep(allAsyncRoutes),res.routes)
        // 2.把用户过滤出来的异步路由增加到路由器中 可以进行路由跳转
        addUserAsyncRoutes(useAsyncRoutes.concat(anyRoute))
        // 3.根据现在用户的最新路由 生成最新菜单
        this.menuRoutes = staticRoutes.concat(useAsyncRoutes,anyRoute)

        return "ok";
      } catch (error) {
        return Promise.reject("fail");
      }
    },
    // 重置用户相关 退出登录和token过期
    reset() {
      // 清除token(pinia以及localStorage) 清除yoghurt信息
      this.token = "";
      localStorage.removeItem("token");
      // console.log(this.userInfo,'this.userInfo')
      this.userInfo = Object.assign(this.userInfo,initUserInfo());
      // 之后何时使用Object.assign  如果对代理对象直接重新赋值时
    },
    // 退出登录
    async logout() {
      try {
        const res = await userApi.logout();
        this.reset();
        // 4.用户退出登录需要清除路由器中的路由 防止下一用户进来还能看到之前用户的路由
        clearRoutes()
        return "ok";
      } catch (error) {
        return Promise.reject("fail");
      }
    },
  },
});
